package plp.imperative1.command;

import plp.expressions2.memory.IdentificadorJaDeclaradoException;
import plp.expressions2.memory.IdentificadorNaoDeclaradoException;
import plp.imperative1.memory.AmbienteCompilacaoImperativa;
import plp.imperative1.memory.AmbienteExecucaoImperativa;
import plp.imperative1.memory.EntradaVaziaException;

public class Paralelismo implements Comando{

    private Comando comando1;
    private Comando comando2;

    public Paralelismo(Comando comando1, Comando comando2){
        this.comando1 = comando1;
        this.comando2 = comando2;
    }

    /**
     * Executa os comandos sequencialmente.
     *
     * @param ambiente o ambiente de execu��o.
     *
     * @return o ambiente depois de modificado pela execu��o
     * dos comandos.
     *
     */
    public AmbienteExecucaoImperativa executar(AmbienteExecucaoImperativa ambienteImp)
        throws IdentificadorJaDeclaradoException, IdentificadorNaoDeclaradoException,
               EntradaVaziaException, InterruptedException {

        AmbienteExecucaoImperativa ambiente1 = (AmbienteExecucaoImperativa) ambienteImp.clone();
        AmbienteExecucaoImperativa ambiente2 = (AmbienteExecucaoImperativa) ambienteImp.clone();

        ThreadCommand thread1 = new ThreadCommand(comando1, ambiente1);
        ThreadCommand thread2 = new ThreadCommand(comando2, ambiente2);
//        ThreadCommand thread1 = new ThreadCommand(comando1, ambienteImp);
//        ThreadCommand thread2 = new ThreadCommand(comando2, ambienteImp);
        thread1.start();
        thread2.start();

        thread1.join();
        thread2.join();

        return ambienteImp;
    }

    /**
     * Realiza a verificacao de tipos dos comandos
     *
     * @param ambiente o ambiente de compila��o.
     * @return <code>true</code> se os comandos s�o bem tipados;
     *          <code>false</code> caso contrario.
     */
    public boolean checaTipo(AmbienteCompilacaoImperativa ambiente)
        throws IdentificadorJaDeclaradoException, IdentificadorNaoDeclaradoException,
               EntradaVaziaException {
        return comando1.checaTipo(ambiente) && comando2.checaTipo(ambiente);
    }
}
